package com.shadowtorcher.TableRolePlayingSystem.controller.WebSocket;

import com.shadowtorcher.TableRolePlayingSystem.DataStructure.DataProcessor;
import com.shadowtorcher.TableRolePlayingSystem.DataStructure.DataSegment;
import com.shadowtorcher.TableRolePlayingSystem.bean.User;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.springframework.web.socket.WebSocketSession;

import javax.crypto.Cipher;
import javax.crypto.NoSuchPaddingException;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class WebSocketUser {
    public static final int WAITING_TO_HANDSHAKE_STEP1 = 1;
    public static final int WAITING_TO_HANDSHAKE_STEP2 = 2;
    public static final int WAITING_TO_HANDSHAKE_STEP3 = 3;
    public static final int LOG_SUCCESS = 4;
    public static final int LOG_FAILURE = 5;
    public int status = WAITING_TO_HANDSHAKE_STEP1;
    private String random;
    private User user;
    private WebSocketSession session;
    private WebSocketRoom room;
    private DataSegment userSegment = null;
    private boolean dm;
    private Cipher userCipher;

    public String getPublicKey() {
        return this.user == null ? "null" : this.user.getPublicKey();
    }

    public String getUserName() {
        return this.user == null ? "null" : this.user.getUserName();
    }

    public String getUserData() {
        return this.user.getUserData();
    }

    public void logOff() {
        this.getRoom().removeUser(this);
    }

    public WebSocketSession getSession() {
        return session;
    }

    public void setSession(WebSocketSession session) {
        this.session = session;
    }

    public DataSegment getUserSegment() {
        if (userSegment == null) {
            userSegment = DataProcessor.buildSegment(user.getUserData());
        }
        return userSegment;
    }


    public void updateUserData() {
        user.setUserData(this.userSegment.toString());
        SaveProcessor.updateUserData(this.user);
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    public WebSocketRoom getRoom() {
        return room;
    }

    public void setRoom(WebSocketRoom room) {
        this.room = room;
    }

    public String getRoomID() {
        return this.getRoom().getGameMap().getRoomID();
    }

    public boolean isDm() {
        return dm;
    }

    public void setDm(boolean dm) {
        this.dm = dm;
    }

    public String getRandom() {
        return random;
    }

    public void setRandom(String random) {
        this.random = random;
    }

    public Cipher getUserEncodeCipher() {
        try {
            if (userCipher == null) {
                java.security.Security.addProvider(new BouncyCastleProvider());
                userCipher = Cipher.getInstance("RSA/None/PKCS1Padding");
                String publicKeyContent = this.user.getPublicKey().replaceAll("\\n", "").replace("-----BEGIN PUBLIC KEY-----", "").replace("-----END PUBLIC KEY-----", "");
                byte[] key = Base64.getDecoder().decode(publicKeyContent);
                X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(key);
                PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(pubKeySpec);
                userCipher.init(Cipher.ENCRYPT_MODE, publicKey);
            }
        } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeySpecException | InvalidKeyException e) {
            e.printStackTrace();
        }
        return userCipher;
    }
}
